package bancosys.tec.persist.entities.domain;

import java.util.ArrayList;
import java.util.Collection;

import javax.persistence.Column;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;

import jmine.tec.persist.annotation.Alias;
import jmine.tec.persist.annotation.Comment;
import jmine.tec.persist.annotation.Comments;
import jmine.tec.persist.annotation.Constraint;
import jmine.tec.persist.annotation.Constraints;
import jmine.tec.persist.annotation.DefaultValue;
import jmine.tec.persist.annotation.Index;
import jmine.tec.persist.annotation.Indexes;
import jmine.tec.persist.annotation.Tablespace;

import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;
import org.hibernate.annotations.Filter;
import org.hibernate.annotations.Filters;
import org.hibernate.annotations.ForeignKey;
import org.hibernate.annotations.Type;

import bancosys.tec.component.Documentation;
import bancosys.tec.persist.authorization.annotation.DisplayName;
import bancosys.tec.persist.base.enumx.ApacheIntValuedEnumMock;
import bancosys.tec.persist.base.enumx.ApacheStringValuedEnumMock;
import bancosys.tec.persist.base.enumx.JavaEnumMock;
import bancosys.tec.persist.bussobj.AuthPersistableBusinessObject;

/**
 * @created 11.07.2007
 * @author Gustavo Almeida
 */
@Entity
@Tablespace(name = "TAB_SPAC_PAI")
@Table(name = "PAI", uniqueConstraints = @UniqueConstraint(columnNames = { "AUTH", "NOME" }))
@Inheritance(strategy = InheritanceType.JOINED)
@Filters({ @Filter(name = "authFilter", condition = "auth = :auth") })
@SequenceGenerator(name = "SEQ_P", sequenceName = "SEQ_P")
@DisplayName("Pai (BO p/ UnitTest)")
@DiscriminatorValue("42")
@jmine.tec.persist.annotation.UniqueConstraint(name = "AK_P_0", columns = { "AUTH", "JAVA_ENUM" })
@Alias("P")
@Documentation("Entidade pai.")
public class PaiAnotado extends AuthPersistableBusinessObject {
    private Long id;

    private PaiAnotado filhoComCascade;

    private PaiAnotado filhoSemCascade;

    private SubPaiAnotado subPaiAnotado;

    private Collection<PaiAnotado> colecaoComCascade = new ArrayList<PaiAnotado>();

    private Collection<PaiAnotado> colecaoSemCascade = new ArrayList<PaiAnotado>();

    private Collection<SubPaiAnotado> colecaoColunaImplicita = new ArrayList<SubPaiAnotado>();

    private String name;

    private JavaEnumMock javaEnumMock;

    private JavaEnumMock outroJavaEnumMock;

    private ApacheIntValuedEnumMock apacheIntEnumMock;

    private ApacheStringValuedEnumMock apacheStringEnumMock;

    @Id
    @Column(name = "ID")
    @GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_P")
    @Documentation("Coluna de identificador.")
    public Long getId() {
        return this.id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    @ManyToMany(fetch = FetchType.LAZY)
    @Cascade({ CascadeType.ALL, CascadeType.DELETE_ORPHAN })
    @JoinTable(name = "PAI_PAI_COM_CASCADE", inverseJoinColumns = { @JoinColumn(name = "PAI_INVERSE_JOIN", nullable = false, updatable = false) }, joinColumns = { @JoinColumn(name = "PAI_JOIN", nullable = false, updatable = false) })
    @DisplayName("Coleção com cascade")
    @Alias("PPCC")
    @ForeignKey(name = "FK_P_PPCC", inverseName = "FK_P_PPCC")
    @Comments({ @Comment(table = "PAI_PAI_COM_CASCADE", value = "Join table do relacionamento de pai com pai com cascade."),
            @Comment(table = "PAI_PAI_COM_CASCADE", column = "PAI_JOIN", value = "Coluna de join."),
            @Comment(table = "PAI_PAI_COM_CASCADE", column = "PAI_INVERSE_JOIN", value = "Coluna de join inverso.") })
    @Index(columns = "PAI_INVERSE_JOIN", suffix = "0")
    public Collection<PaiAnotado> getColecaoComCascade() {
        return this.colecaoComCascade;
    }

    public void setColecaoComCascade(Collection<PaiAnotado> colecaoComCascade) {
        this.colecaoComCascade = colecaoComCascade;
    }

    @ManyToMany(fetch = FetchType.LAZY)
    @JoinTable(name = "PAI_PAI_SEM_CASCADE", inverseJoinColumns = { @JoinColumn(name = "PAI_INVERSE_JOIN", nullable = false, updatable = false) }, joinColumns = { @JoinColumn(name = "PAI_JOIN", nullable = false, updatable = false) })
    @DisplayName("Coleção sem cascade")
    @Alias("PPSC")
    @ForeignKey(name = "FK_P_PPSC", inverseName = "FK_P_PPSC")
    @Comments({ @Comment(table = "PAI_PAI_SEM_CASCADE", value = "Coluna de join inverso."),
            @Comment(table = "PAI_PAI_SEM_CASCADE", column = "PAI_JOIN", value = "Coluna de join inverso."),
            @Comment(table = "PAI_PAI_SEM_CASCADE", column = "PAI_INVERSE_JOIN", value = "Coluna de join inverso.") })
    @Indexes({ @Index(columns = { "PAI_INVERSE_JOIN", "PAI_JOIN" }, suffix = "0"), @Index(columns = { "PAI_INVERSE_JOIN" }, suffix = "1"),
            @Index(columns = { "PAI_JOIN ASC" }, suffix = "2") })
    public Collection<PaiAnotado> getColecaoSemCascade() {
        return this.colecaoSemCascade;
    }

    public void setColecaoSemCascade(Collection<PaiAnotado> colecaoSemCascade) {
        this.colecaoSemCascade = colecaoSemCascade;
    }

    @ManyToOne(fetch = FetchType.LAZY)
    @Cascade({ CascadeType.ALL })
    @JoinColumn(name = "FILHO_COM_CASCADE")
    @ForeignKey(name = "FK_P_P")
    @DisplayName("Filho com cascade")
    @Documentation("Coluna de join com pai.")
    public PaiAnotado getFilhoComCascade() {
        return this.filhoComCascade;
    }

    public void setFilhoComCascade(PaiAnotado filhoComCascade) {
        this.filhoComCascade = filhoComCascade;
    }

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "FILHO_SEM_CASCADE")
    @Comment(table = "PAI", column = "FILHO_SEM_CASCADE", value = "SEM COMENTARIOS.")
    @ForeignKey(name = "FK_P_P")
    @DisplayName("Filho sem cascade")
    public PaiAnotado getFilhoSemCascade() {
        return this.filhoSemCascade;
    }

    public void setFilhoSemCascade(PaiAnotado filhoSemCascade) {
        this.filhoSemCascade = filhoSemCascade;
    }

    /**
     * @return
     */
    @Column(name = "NOME")
    @DisplayName("Nome")
    @Documentation("Coluna com o nome da entidade pai.")
    public String getName() {
        return this.name;
    }

    /**
     * Define o name.
     * 
     * @param name O name a ser definido.
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * @return the javaEnumMock
     */
    @Column(name = "JAVA_ENUM")
    @Documentation("Comment da coluna de java enum.")
    @DefaultValue("0")
    @Constraints({ @Constraint(condition = "JAVA_ENUM < 1 AND JAVA_ENUM > -1", suffix = "3") })
    public JavaEnumMock getJavaEnumMock() {
        return this.javaEnumMock;
    }

    // @Index(columns = "NOME DESC", suffix = "2")

    /**
     * @param javaEnumMock the javaEnumMock to set
     */
    public void setJavaEnumMock(JavaEnumMock javaEnumMock) {
        this.javaEnumMock = javaEnumMock;
    }

    /**
     * @return the apacheIntEnumMock
     */
    @Type(type = "bancosys.tec.persist.base.enumx.ApacheIntValuedEnumMockType")
    @Column(name = "APACHE_INT_ENUM")
    @Comment(table = "PAI", column = "APACHE_INT_ENUM", value = "SEM COMENTARIOS.")
    @Constraint(suffix = "0")
    @Index(columns = { "APACHE_INT_ENUM ASC", "APACHE_STRING_ENUM ASC" }, suffix = "1")
    public ApacheIntValuedEnumMock getApacheIntEnumMock() {
        return this.apacheIntEnumMock;
    }

    /**
     * @param apacheIntEnumMock the apacheIntEnumMock to set
     */
    public void setApacheIntEnumMock(ApacheIntValuedEnumMock apacheIntEnumMock) {
        this.apacheIntEnumMock = apacheIntEnumMock;
    }

    /**
     * @return the apacheStringEnumMock
     */
    @Type(type = "bancosys.tec.persist.base.enumx.ApacheStringValuedEnumMockType")
    @Column(name = "APACHE_STRING_ENUM")
    @Comment(table = "PAI", column = "APACHE_STRING_ENUM", value = "SEM COMENTARIOS.")
    @DefaultValue("'AV'")
    @Constraint(suffix = "1")
    public ApacheStringValuedEnumMock getApacheStringEnumMock() {
        return this.apacheStringEnumMock;
    }

    /**
     * @param apacheStringEnumMock the apacheStringEnumMock to set
     */
    public void setApacheStringEnumMock(ApacheStringValuedEnumMock apacheStringEnumMock) {
        this.apacheStringEnumMock = apacheStringEnumMock;
    }

    /**
     * @return the outroJavaEnumMock
     */
    @Column(name = "OUTRO_JAVA_ENUM")
    @Comment(table = "PAI", column = "OUTRO_JAVA_ENUM", value = "SEM COMENTARIOS.")
    @Constraint(suffix = "2")
    @Index(columns = { "NOME ASC", "OUTRO_JAVA_ENUM DESC" }, suffix = "0")
    public JavaEnumMock getOutroJavaEnumMock() {
        return this.outroJavaEnumMock;
    }

    /**
     * @param outroJavaEnumMock the outroJavaEnumMock to set
     */
    public void setOutroJavaEnumMock(JavaEnumMock outroJavaEnumMock) {
        this.outroJavaEnumMock = outroJavaEnumMock;
    }

    @Override
    public String toString() {
        return "Pai(" + this.id + "," + this.name + ")";
    }

    /**
     * @return the colecaoColunaImplicita
     */
    @OneToMany
    @Index(name = "IX_SP_2")
    @Documentation("Coluna de join definida em propriedade em PaiAnotado.")
    @JoinColumn(name = "COD_COLLECTION_PAI_ANOTADO")
    @ForeignKey(name = "FK_P_SP")
    public Collection<SubPaiAnotado> getColecaoColunaImplicita() {
        return this.colecaoColunaImplicita;
    }

    /**
     * @param colecaoColunaImplicita the colecaoColunaImplicita to set
     */
    public void setColecaoColunaImplicita(Collection<SubPaiAnotado> colecaoColunaImplicita) {
        this.colecaoColunaImplicita = colecaoColunaImplicita;
    }

    /**
     * @return the subPaiAnotado
     */
    @ManyToOne
    @JoinColumn(name = "COD_SUB_PAI_ANOTADO")
    @Comment(table = "PAI", column = "COD_SUB_PAI_ANOTADO", value = "SEM COMENTARIOS.")
    public SubPaiAnotado getSubPaiAnotado() {
        return this.subPaiAnotado;
    }

    /**
     * @param subPaiAnotado the subPaiAnotado to set
     */
    public void setSubPaiAnotado(SubPaiAnotado subPaiAnotado) {
        this.subPaiAnotado = subPaiAnotado;
    }

}